package com.jx.mlxg.api;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jx.mlxg.entity.*;
import com.jx.mlxg.mapper.*;
import com.jx.mlxg.service.ApprovalRecordService;
import com.jx.mlxg.service.OrderDetailsService;
import com.jx.mlxg.utils.HttpClientUtil;
//import com.jx.mlxg.utils.HttpUtils;
import com.jx.mlxg.utils.play.WxPlay;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.model.Refund;
import com.wechat.pay.java.core.exception.ServiceException;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.web.bind.annotation.RequestBody;

@Slf4j
@RestController
@RequestMapping("/wxApi")
public class PlayWxApiController {

    @Resource
    private OrderDetailsMapper orderDetailsMapper;

    @Resource
    private ProductMapper productMapper;

    @Resource
    private OrdersMapper ordersMapper;

    @Resource
    private ShippingInfoMapper shippingInfoMapper;

    @Resource
    private ApprovalRecordService approvalRecordService;

    @Resource
    private WxpusherUserUidMapper  wxpusherUserUidMapper;

    @Resource
    private AddressesMapper addressesMapper;

    private static final String WX_Pusher_API = "https://wxpusher.zjiecode.com/api/send/message";



    /**
     * 微信支付回调接口
     * 文档参考：https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_5.shtml
     *
     * @param request HTTP请求对象
     * @return 返回处理结果（必须返回成功响应防止微信重复通知）
     */
    @PostMapping("/notice")
    public ResponseEntity<?> wxPaymentCallback(HttpServletRequest request) {
        // 初始化返回结果（微信要求成功时返回特定JSON）
        String successResponse = "{\"code\": \"SUCCESS\", \"message\": \"成功\"}";

        try {
            // 1. 从请求头获取微信支付参数（验签需要）
            String signature = request.getHeader("Wechatpay-Signature");
            String timestamp = request.getHeader("Wechatpay-Timestamp");
            String nonce = request.getHeader("Wechatpay-Nonce");
            String serialNumber = request.getHeader("Wechatpay-Serial");

            // 2. 读取请求体内容
            String body = request.getReader().lines().collect(Collectors.joining());
            log.debug("收到微信支付回调，原始数据：{}", body);

            // 3. 构造请求参数对象
            RequestParam requestParam = new RequestParam.Builder()
                    .serialNumber(serialNumber)
                    .nonce(nonce)
                    .signature(signature)
                    .timestamp(timestamp)
                    .body(body)
                    .build();

            // 4. 使用配置初始化解析器（确保WxPlay.config已正确配置）
            NotificationParser parser = new NotificationParser((NotificationConfig) WxPlay.config);

            // 5. 解析并验签回调数据
            Transaction transaction = parser.parse(requestParam, Transaction.class);
            log.info("解析后的交易数据：{}", JSONUtil.toJsonStr(transaction));

            // 6. 基础校验
            if (!"支付成功".equals(transaction.getTradeStateDesc())) {
                log.warn("支付未成功，交易状态：{}", transaction.getTradeState());
                return ResponseEntity.ok().body(successResponse);
            }

            // 7. 获取关键参数
            String mchId = transaction.getMchid();          // 商户号
            String appId = transaction.getAppid();           // 应用ID
            String orderNo = transaction.getOutTradeNo();    // 商户订单号
            int amount = transaction.getAmount().getTotal(); // 总金额（单位：分）

            // 8. 验证商户号（防止非法请求）
            if (!"1725596634".equals(mchId)) {
                log.error("商户号校验失败，预期：1725596634，实际：{}", mchId);
                return ResponseEntity.ok().body(successResponse);
            }

            // 9. 处理业务逻辑（示例）
            handlePaymentSuccess(orderNo, amount);

        } catch (Exception e) {
            log.error("处理微信支付回调异常", e);
            // 注意：即使处理失败也要返回成功，否则微信会重复通知
            // 实际应通过日志告警系统通知开发人员
        }

        // 10. 返回成功响应（必须返回指定格式）
        return ResponseEntity.ok().body(successResponse);
    }

    /**
     * 处理支付成功业务逻辑
     * @param orderNo 商户订单号（对应orders表的order_id）
     * @param wxAmount 微信支付金额（单位：分）
     */
    private void handlePaymentSuccess(String orderNo, int wxAmount) {
        try {
            // 1. 查询本地订单
            Orders order = ordersMapper.selectByOrderId(orderNo);
            if (order == null) {
                log.error("订单不存在，orderNo: {}", orderNo);
                return;
            }

            // 2. 检查订单状态（幂等性校验）
            if ("已支付".equals(order.getStatus())) {
                log.info("订单已处理，直接返回。orderNo: {}", orderNo);
                return;
            }

            // 3. 验证金额（微信金额单位是分，数据库是元）
            BigDecimal orderAmount = order.getRealAmount();
            BigDecimal wxAmountYuan = BigDecimal.valueOf(wxAmount).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);

            if (wxAmountYuan.compareTo(orderAmount) != 0) {
                log.error("金额不一致，订单金额：{}元，支付金额：{}元", orderAmount, wxAmountYuan);
                // 这里可以记录异常订单，触发告警
                return;
            }

            // 4. 更新订单状态
            boolean updateSuccess = updateOrderStatus(orderNo);
            if (!updateSuccess) {
                log.error("订单状态更新失败，orderNo: {}", orderNo);
                return;
            }

            // 5. 处理后续业务
            handlePostPayment(orderNo);

        } catch (Exception e) {
            log.error("处理订单业务异常，orderNo: {}", orderNo, e);
            // 可记录到异常表或发送告警通知
        }
    }

    private boolean updateOrderStatus(String orderNo) {
        Orders updateOrder = new Orders();
        updateOrder.setOrderId(orderNo);
        updateOrder.setStatus("已支付");
//        updateOrder.setShippedDate(LocalDateTime.now()); // 根据业务需求设置发货时间

        return ordersMapper.updateById(updateOrder) > 0;
    }

    @Transactional
    protected void handlePostPayment(String orderNo) throws IOException {
        // 扣减库存
        List<OrderDetails> details = orderDetailsMapper.selectList(
                new QueryWrapper<OrderDetails>().eq("order_id", orderNo)
        );

        for (OrderDetails detail : details) {
            Product product = productMapper.selectById(detail.getProductId());
            if (product == null) {
                throw new RuntimeException("商品不存在: " + detail.getProductId());
            }

            int newStock = product.getStock() - detail.getQuantity();
            if (newStock < 0) {
                throw new RuntimeException("库存不足，商品ID: " + product.getProductId());
            }

            Product updateProduct = new Product();
            updateProduct.setProductId(product.getProductId());
            updateProduct.setStock(newStock);
            productMapper.updateById(updateProduct);
        }

//        // 生成发货单（示例）
//        ShippingInfo shippingInfo = new ShippingInfo();
        Orders order = ordersMapper.selectById(orderNo);
//        // 根据订单信息填充发货信息...
//        shippingInfoMapper.insert(shippingInfo);
        //创建订单自带审批流
        ApprovalRecord approvalRecord = new ApprovalRecord();
        approvalRecord.setOrderId(orderNo);
        approvalRecord.setNodeId(1);
//        approvalRecord.setUsersId(byOpenId.getUserId());
        approvalRecord.setApproveStatus("审批中");
        approvalRecord.setApproveTime(LocalDateTime.now());
        approvalRecordService.save(approvalRecord);
        // 发送通知（异步处理）
        sendPaymentSuccessNotification(order);
    }

/*    // 异步通知方法
    @Async
    public void sendPaymentSuccessNotification(Orders orders) throws IOException {
        // 实现通知逻辑（短信、微信模板消息等）
        log.info("发送支付成功通知，订单号：{}", orders.getOrderId());
        String url  = "https://wxpusher.zjiecode.com/api/send/message/simple-push";
        QueryWrapper<ShippingInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", orders.getOrderId());
        ShippingInfo shippingInfo = shippingInfoMapper.selectOne(queryWrapper);
        String name = shippingInfo.getRecipientName();//用户名
        String phoneNumber = shippingInfo.getPhoneNumber();//手机号码
        String address = shippingInfo.getAddress();//详细地址


//        HashMap<String, Object> map = new HashMap<>();
//        ArrayList<Object> list = new ArrayList<>();
//        list.add(39957);
//        ArrayList<Object> list1 = new ArrayList<>();
//        list1.add("UID_oFywpZvxQiYAyc7VWiyfE2fKXnFx");
//        map.put("apptoken","AT_T8HBakxqYHOAyDfATF42sQq7PJIOG1oL");
//        map.put("content","\n" +
//                "<h1>\uF4E6 订单编号：KH-1233001</h1><h5 style=\\\"color: #606266; border-bottom: 1px solid #e4e7ed; padding-bottom: 8px\\\">物流信息详情</h5><p><strong>\uF464 收货人：</strong> 王先生</p><p><strong>\uF3E0 收货地址：</strong> 北京市海淀区飓风街道海淀五路居一号楼3单元401<br/><small style=\\\"color: #909399\\\">(门口拍照即可)</small></p><p><strong>\uF4F1 联系电话：</strong> 132-4447-7912</p><h5 style=\\\"color: #f56c6c; background: #fef0f0; padding: 8px; border-radius: 4px\\\">⚠\uFE0F 请尽快安排此客户订单发货，并将快递单号回填审批流程</h5>");
//        map.put("summary","\n" +
//                "订单编号:KH-1233001");
//        map.put("contentType","1");
//        map.put("topicIds",list);
//        map.put("uids" ,list1);
        HttpClientUtil.doPost(url,map);
    }*/
@Async
public void sendPaymentSuccessNotification(Orders orders) {
    try {
        // 1. 获取订单信息
        String orderId = orders.getOrderId();
        log.info("发送支付成功通知，订单号：{}", orderId);

        // 2. 查询收货信息
        ShippingInfo shippingInfo = getShippingInfoByOrderId(orderId);
        if (shippingInfo == null) {
            log.error("订单 {} 的收货信息不存在", orderId);
            return;
        }

        // 3. 构造通知内容
        JSONObject jsonBody = constructNotificationJson(orders, shippingInfo);

// 4. 发送通知
        String response = HttpClientUtil.doPost4JsonObject(WX_Pusher_API, jsonBody);

        // 5. 处理响应结果
        handleResponse(response, orderId);
    } catch (Exception e) {
        log.error("发送支付成功通知失败，订单号：{}", orders.getOrderId(), e);
        // 可以考虑重试机制或者将失败任务存入数据库稍后重试
    }
}

    private ShippingInfo getShippingInfoByOrderId(String orderId) {
        try {
            QueryWrapper<ShippingInfo> queryWrapper = new QueryWrapper<ShippingInfo>();
            queryWrapper.eq("order_id", orderId);
            ShippingInfo shippingInfo = shippingInfoMapper.selectOne(queryWrapper);
            return shippingInfo;
        } catch (Exception e) {
            log.error("查询订单 {} 的收货信息失败", orderId, e);
            return null;
        }
    }

    private JSONObject constructNotificationJson(Orders orders, ShippingInfo shippingInfo) {
    log.info("constructNotificationJson方法进入");
        JSONObject json = new JSONObject();
        Addresses addresses = addressesMapper.selectById(shippingInfo.getAddressId());
        String province = addresses.getProvince();
        String city = addresses.getCity();
        String area = addresses.getArea();
        String houseNumber = addresses.getHouseNumber();
        String address = province + city + area + houseNumber;
        log.info("WxPusher的地址参数为：{}",address);
        json.put("appToken", "AT_T8HBakxqYHOAyDfATF42sQq7PJIOG1oL");
        json.put("content", String.format("<h1>📦 订单编号：%s</h1>" +
                        "<h5 style='color: #606266; border-bottom: 1px solid #e4e7ed; padding-bottom: 8px'>物流信息详情</h5>" +
                        "<h5 style='color: #909399; margin: 12px 0 4px 0'>👤 收货人：</h5><p style='color: #409EFF; margin: 0 0 12px 20px'>%s</p>" +
                        "<h5 style='color: #909399; margin: 12px 0 4px 0'>🏠 收货地址：</h5><p style='color: #409EFF; margin: 0 0 12px 20px'>%s</p>" +
                        "<h5 style='color: #909399; margin: 12px 0 4px 0'>📱 联系电话：</h5><p style='color: #409EFF; margin: 0 0 20px 20px'>%s</p>" +
                        "<h5 style='color: #f56c6c; background: #fef0f0; padding: 8px; border-radius: 4px'>⚠️ 请尽快安排此客户发货</h5>",
                orders.getOrderId(),
                shippingInfo.getRecipientName(),
                address,
                shippingInfo.getPhoneNumber()));

        json.put("summary", "订单编号:" + orders.getOrderId());
        json.put("contentType",2);
//        json.put("topicIds", new Integer[]{39957});

        // 获取可用的 uids 列表
        List<WxpusherUserUid> uidList = wxpusherUserUidMapper.selectList(
                new LambdaQueryWrapper<WxpusherUserUid>()
                        .eq(WxpusherUserUid::getStatus, 1)
        );

// 提取 uid
        List<String> uids = new ArrayList<>();
        for (WxpusherUserUid item : uidList) {
            uids.add(item.getUid());
        }
        log.info("uids: {}", uids);
        json.put("uids", uids);

        return json;
    }

    private void handleResponse(String response, String orderId) {
        log.info("支付成功通知响应：订单 {}，响应内容：{}", orderId, response);
        // 可以根据响应结果进行进一步处理，如记录通知状态等
    }

    /**
     * 申请退款接口
     * 用于商户后台发起退款请求
     */
    @PostMapping("/applyRefund")
    public ResponseEntity<?> applyRefund(@RequestBody Map<String, Object> refundRequest) {
        log.info("收到退款申请请求：{}", refundRequest);
        try {
            // 1. 获取请求参数
            String orderId = (String) refundRequest.get("orderId");
            BigDecimal refundAmount = new BigDecimal((String) refundRequest.get("refundAmount"));
            String refundReason = (String) refundRequest.get("refundReason");

            // 2. 校验参数
            if (orderId == null || refundAmount == null || refundReason == null) {
                log.error("退款参数不完整");
                return ResponseEntity.badRequest().body("参数不完整");
            }

            // 3. 查询订单信息
            Orders order = ordersMapper.selectByOrderId(orderId);
            if (order == null) {
                log.error("订单不存在：{}", orderId);
                return ResponseEntity.badRequest().body("订单不存在");
            }

            // 4. 检查订单状态，只有已支付的订单才能退款
            if (!"已支付".equals(order.getStatus())) {
                log.error("订单状态不允许退款：{}，当前状态：{}", orderId, order.getStatus());
                return ResponseEntity.badRequest().body("订单状态不允许退款");
            }

            // 5. 调用微信支付退款API
            Refund refund = WxPlay.applyRefund(order, refundAmount, refundReason);

            // 6. 更新订单状态为退款中
            Orders updateOrder = new Orders();
            updateOrder.setOrderId(orderId);
            updateOrder.setStatus("退款中");
            ordersMapper.updateById(updateOrder);

            // 7. 构造返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("code", 200);
            result.put("message", "退款申请成功");
            result.put("data", refund);

            return ResponseEntity.ok(result);
        } catch (ServiceException e) {
            log.error("微信退款API调用失败：{}", e.getErrorMessage());
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("code", 500);
            errorResult.put("message", "退款失败：" + e.getErrorMessage());
            return ResponseEntity.status(500).body(errorResult);
        } catch (Exception e) {
            log.error("退款申请处理异常：", e);
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("code", 500);
            errorResult.put("message", "系统异常，请稍后重试");
            return ResponseEntity.status(500).body(errorResult);
        }
    }

    /**
     * 退款回调接口
     * 微信支付退款结果通知
     */
  /*  @PostMapping("/refundNotice")
    public ResponseEntity<?> refundNotice(HttpServletRequest request) {
        log.info("收到退款回调通知");
        try {
            // 1. 构造响应对象
            String successResponse = "{\"code\":\"SUCCESS\",\"message\":\"成功\"}";

            // 2. 获取回调数据
            String body = HttpUtils.readData(request);
            String serial = request.getHeader("Wechatpay-Serial");
            String signature = request.getHeader("Wechatpay-Signature");
            String timestamp = request.getHeader("Wechatpay-Timestamp");
            String nonce = request.getHeader("Wechatpay-Nonce");

            // 3. 构造请求参数
            RequestParam requestParam = new RequestParam.Builder()
                    .serialNumber(serial)
                    .nonce(nonce)
                    .signature(signature)
                    .timestamp(timestamp)
                    .body(body)
                    .build();

            // 4. 解析回调数据
            NotificationParser parser = new NotificationParser((NotificationConfig) WxPlay.config);
            Refund refund = parser.parse(requestParam, Refund.class);
            log.info("解析后的退款数据：{}", JSONUtil.toJsonStr(refund));

            // 5. 处理退款结果
            handleRefundResult(refund);

            // 6. 返回成功响应
            return ResponseEntity.ok().body(successResponse);
        } catch (Exception e) {
            log.error("退款回调处理异常：", e);
            // 即使处理失败，也返回成功响应给微信，避免重复通知
            return ResponseEntity.ok().body("{\"code\":\"SUCCESS\",\"message\":\"成功\"}");
        }
    }*/

    /**
     * 处理退款结果
     * 更新订单状态和处理相关业务
     */
    @Transactional
    void handleRefundResult(Refund refund) {
        try {
            // 1. 获取退款相关信息
            String orderId = refund.getOutTradeNo();
            String refundStatus = null;
            // 安全获取退款状态，处理微信回调数据中status为null的情况
            if (refund.getStatus() != null) {
                refundStatus = refund.getStatus().toString();
            } else {
                // 如果status为null，尝试从successTime字段判断
                if (refund.getSuccessTime() != null) {
                    refundStatus = "SUCCESS"; // 有成功时间，说明退款成功
                } else {
                    refundStatus = "UNKNOWN"; // 未知状态
                }
                log.warn("退款状态为null，通过其他字段推断状态为：{}", refundStatus);
            }
            String refundId = refund.getRefundId();

            log.info("处理退款结果：订单号={}, 退款状态={}, 退款ID={}", orderId, refundStatus, refundId);

            // 2. 查询订单
            Orders order = ordersMapper.selectByOrderId(orderId);
            if (order == null) {
                log.error("订单不存在：{}", orderId);
                return;
            }

            // 3. 根据退款状态更新订单状态
            if ("SUCCESS".equals(refundStatus)) {
                // 退款成功
                Orders updateOrder = new Orders();
                updateOrder.setOrderId(orderId);
                updateOrder.setStatus("已退款");
                ordersMapper.updateById(updateOrder);

                // 4. 发送退款成功通知
                sendRefundSuccessNotification(order);

                log.info("订单退款成功：{}", orderId);
            } else if ("CLOSED".equals(refundStatus)) {
                // 退款关闭
                Orders updateOrder = new Orders();
                updateOrder.setOrderId(orderId);
                updateOrder.setStatus("退款关闭");
                ordersMapper.updateById(updateOrder);

                log.info("订单退款关闭：{}", orderId);
            } else if ("ABNORMAL".equals(refundStatus)) {
                // 退款异常
                log.error("订单退款异常：{}, 退款状态：{}", orderId, refundStatus);
                // 可以添加告警处理
            } else if ("UNKNOWN".equals(refundStatus)) {
                // 未知状态，但已经通过successTime推断过了
                log.warn("订单退款状态未知：{}", orderId);
                // 由于已经在前面根据successTime设置了refundStatus为SUCCESS，这里不应该会被执行到
            } else {
                // 其他未预期的状态
                log.warn("收到未预期的退款状态：{}，订单号：{}", refundStatus, orderId);
            }
        } catch (Exception e) {
            log.error("处理退款结果异常：", e);
            // 事务会自动回滚
        }
    }

    /**
     * 查询退款状态接口
     */
    @PostMapping("/queryRefund")
    public ResponseEntity<?> queryRefund(@RequestBody Map<String, String> request) {
        log.info("查询退款状态请求：{}", request);
        try {
            String outRefundNo = request.get("outRefundNo");
            if (outRefundNo == null) {
                return ResponseEntity.badRequest().body("退款单号不能为空");
            }

            Refund refund = WxPlay.queryRefund(outRefundNo);
            if (refund == null) {
                return ResponseEntity.badRequest().body("退款记录不存在");
            }

            Map<String, Object> result = new HashMap<>();
            result.put("code", 200);
            result.put("message", "查询成功");
            result.put("data", refund);

            return ResponseEntity.ok(result);
        } catch (Exception e) {
            log.error("查询退款状态异常：", e);
            return ResponseEntity.status(500).body("查询失败，请稍后重试");
        }
    }

    /**
     * 发送退款成功通知
     */
    @Async
    public void sendRefundSuccessNotification(Orders order) {
        try {
            // 1. 获取订单信息
            String orderId = order.getOrderId();
            log.info("发送退款成功通知，订单号：{}", orderId);

            // 2. 构造通知内容
            JSONObject jsonBody = new JSONObject();
            jsonBody.put("appToken", "AT_T8HBakxqYHOAyDfATF42sQq7PJIOG1oL");
            jsonBody.put("content", String.format("<h1>💰 退款成功通知</h1>" +
                            "<h5 style='color: #606266; border-bottom: 1px solid #e4e7ed; padding-bottom: 8px'>订单信息</h5>" +
                            "<h5 style='color: #909399; margin: 12px 0 4px 0'>📦 订单编号：</h5><p style='color: #409EFF; margin: 0 0 12px 20px'>%s</p>" +
                            "<h5 style='color: #909399; margin: 12px 0 4px 0'>💵 退款金额：</h5><p style='color: #f56c6c; margin: 0 0 20px 20px'>¥%s</p>" +
                            "<p style='color: #67c23a'>退款已成功原路返回，请留意账户到账通知</p>",
                    order.getOrderId(),
                    order.getRealAmount().toString()));

            jsonBody.put("summary", "退款成功：" + order.getOrderId());
            jsonBody.put("contentType", 2);

            // 3. 获取用户的uid列表
            List<WxpusherUserUid> uidList = wxpusherUserUidMapper.selectList(
                    new LambdaQueryWrapper<WxpusherUserUid>()
                            .eq(WxpusherUserUid::getStatus, 1)
            );

            List<String> uids = new ArrayList<>();
            for (WxpusherUserUid item : uidList) {
                uids.add(item.getUid());
            }
            log.info("退款通知uids: {}", uids);
            jsonBody.put("uids", uids);

            // 4. 发送通知
            String response = HttpClientUtil.doPost4JsonObject(WX_Pusher_API, jsonBody);

            // 5. 处理响应结果
            log.info("退款成功通知响应：订单 {}，响应内容：{}", orderId, response);
        } catch (Exception e) {
            log.error("发送退款成功通知失败，订单号：{}", order.getOrderId(), e);
        }
    }
}
